`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/06 10:30:46
// Design Name: 
// Module Name: cu
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module cu(
    opcode,funct3,funct7,op_imm,op_rd,op_alu,op_w,op_pc
    );

    input [6:0] opcode;
    input [2:0] funct3;
    input [6:0] funct7;
    output reg [2:0] op_alu;
    output reg [2:0] op_imm;
    output reg [1:0] op_rd;
    output reg [1:0] op_pc;
    output reg  op_w;

    parameter arith_r=7'b0110011,arith_i=7'b0010011,load=7'b0000011,store=7'b0100011,jal=7'b1101111,jalr=7'b1100111,branch=7'b1100011;

    parameter arith_r_add=10'b0000000000,arith_r_sub=10'b0000100000;
    
    parameter arith_i_add=3'b000;

    always @(*) begin
        case (opcode)
            arith_r : begin
                case({funct3,funct7})
                    arith_r_add : begin
                        op_alu = 3'b000;
                    end
                    arith_r_sub : begin
                        op_alu = 3'b001;
                    end
                    default : begin
                        op_alu = 3'b000;
                    end
                endcase
                op_imm = 3'b000;
                op_rd = 2'b00;
                op_w = 1'b0;
                op_pc = 2'b00;
            end 
            arith_i : begin
                case(funct3)
                    arith_i_add : begin
                        op_alu = 3'b000;
                    end
                    default : begin
                        op_alu = 3'b000;
                    end
                endcase
                op_imm = 3'b001;
                op_rd = 2'b00;
                op_w = 1'b0;
                op_pc = 2'b00;
            end
            load : begin
                op_imm = 3'b001;
                op_rd = 2'b10;
                op_alu = 3'b000;
                op_w = 1'b0;
                op_pc = 2'b00;
            end  
            store : begin
                op_imm = 3'b010;
                op_rd = 2'b00;
                op_alu = 3'b000;
                op_w = 1'b1;
                op_pc = 2'b00;
            end 
            jal : begin
                op_imm = 3'b100;
                op_rd = 2'b01;
                op_alu = 3'b010;
                op_w = 1'b0;
                op_pc = 2'b01;
            end
            jalr : begin
                op_imm = 3'b100;
                op_rd = 2'b01;
                op_alu = 3'b010;
                op_w = 1'b0;
                op_pc = 2'b01;
            end
            branch :  begin
                op_imm = 3'b011;
                op_rd = 2'b11;
                op_alu = 3'b001;
                op_w = 1'b0;
                op_pc = 2'b10;
            end 
            default : begin
                op_imm = 3'b011;
                op_rd = 2'b11;
                op_alu = 3'b001;
                op_w = 1'b0;
                op_pc = 2'b00;
            end
        endcase
    end
endmodule
